package jmars.mobile.worker;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import jmars.mobile.common.Investigator;
import jmars.mobile.common.PropertiesLoader;
import jmars.mobile.datainvestigation.Summary;
import jmars.mobile.domain.markov.State;

/**
 * 
 * 
 * @author Jan
 *
 */
public class Markov implements Investigator {

	private long getTimeKey(Long time,Long interval){
		return time-time%interval;
	}
	@SuppressWarnings("unused")
	private long getTimeKey(Date time,Long interval){
		return getTimeKey(time.getTime(),interval);
	}
	
	@Override
	public Long compute(File[] files, FileWriter writer) throws IOException, ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat(Summary.dateFormat);
		DecimalFormat df = new DecimalFormat("0.00");
		String pro=PropertiesLoader.getProperty("time.beginDate");
		Date begin = (pro==null||"".equals(pro))?null:sdf.parse(pro);
		pro=PropertiesLoader.getProperty("time.endDate");
		Date end = (pro==null||"".equals(pro))?null:sdf.parse(pro);
		Long interval = Long.parseLong(PropertiesLoader.getProperty("time.interval"));
		if(interval==null)interval=1000L;
		
		Long total = 0L;
		FileInputStream fis;
		BufferedReader reader;
		String row;
		String[] cols;
		Date currentBegin;
		String bts,btsf[]=null,btst[]=null;
		Long timef = null;
		State from = null, to = null;
		Map<String,Map<Long,String>> seq=new HashMap<String,Map<Long,String>>(10000000,0.9F);
		ArrayList<Entry<Long,String>> al;
		Entry<Long,String> seqEntry=null;
		//State.init(2*60*90000, 0.9F);
		int t,l;
		for(File inputFile:files){
			fis = new FileInputStream(inputFile);
			reader = new BufferedReader(new InputStreamReader(fis));
			while((row=reader.readLine())!=null){
				cols=row.split(Summary.columnSeperator);
				if(cols.length<Summary.columnCount) continue;
				currentBegin=sdf.parse(cols[5]);
				if(end!=null&&currentBegin.getTime()>end.getTime()+1*60*60*1000)break;
				if((begin!=null&&currentBegin.getTime()<begin.getTime())||(end!=null&&currentBegin.getTime()>end.getTime()))continue;
				total++;
				bts=cols[1]+"_"+cols[2];
				if(!seq.containsKey(cols[0]))
					seq.put(cols[0], new HashMap<Long,String>());
				seq.get(cols[0]).put(currentBegin.getTime(), bts);
			}
			for(String tk:seq.keySet()){
				al = new ArrayList<Entry<Long,String>>(seq.get(tk).entrySet());    

		        Collections.sort(al, new Comparator<Map.Entry<Long,String>>() {
		            public int compare(Map.Entry<Long,String> o1, Map.Entry<Long,String> o2) {
		                return o2.getKey()==o1.getKey()?0:(o2.getKey()<o1.getKey()?1:-1);
		            }
		        });
		        from=null;
				for(t=0,l=al.size();t<l;t++){
					seqEntry=al.get(t);
					btst=seqEntry.getValue().split("_");
					if(btsf!=null){
						if((Summary.filterLac==null||Summary.filterLac.equals(",,")||Summary.filterLac.indexOf(","+btsf[0]+",")!=-1)
								&&
							(Summary.filterCI==null||Summary.filterCI.equals(",,")||Summary.filterCI.indexOf(","+btsf[1]+",")!=-1))
							from=State.createInstance(btsf[0]+"_"+btsf[1],getTimeKey(timef,interval));
						else
							from=null;
						
						if((Summary.filterLac==null||Summary.filterLac.equals(",,")||Summary.filterLac.indexOf(","+btst[0]+",")!=-1)
								&&
							(Summary.filterCI==null||Summary.filterCI.equals(",,")||Summary.filterCI.indexOf(","+btst[1]+",")!=-1))
							to=State.createInstance(seqEntry.getValue(),getTimeKey(seqEntry.getKey(),interval));
						else
							to=null;
						if(from==null&&to==null)break;
						if(from==null&&to!=null) from=State.createInstance(null, getTimeKey(timef,interval));
						if(from!=null&&to==null) to=State.createInstance(null, getTimeKey(seqEntry.getKey(),interval));
						State.addLink(from, to);
						from.addCount(1);
						if(t==l-1)to.addCount(1);
					}
					btsf=btst;
					timef=seqEntry.getKey();
				}
				seq.get(tk).clear();
				if(seqEntry!=null)seq.get(tk).put(seqEntry.getKey(), seqEntry.getValue());
			}
			reader.close();
			fis.close();
			System.gc();
			System.out.println(inputFile.getName()+" finished at "+total);
		}
		System.out.println("begin write");
		writer.write("%*****************details******************\r\n%");
		for(String fbs:State.getBtsPool()){
			for(Long ft:State.getTimes()){
				for(String tbs:State.getBtsPool()){
					for(Long tt:State.getTimes()){
						from=State.getState(fbs, ft);
						if(from==null)
							writer.write(0);
						else
							writer.write(df.format(((float)from.getOutLink(tbs, tt))/((float)from.getCount())));
					}
					writer.write(",");
				}
				writer.write("\r\n");
			}System.out.println("begin write*********");
			writer.write("*********************\r\n");
		}
		return total;
	}

}
